package com.dyna.gateway.utils;

import com.alibaba.fastjson.JSON;
import com.dyna.constants.TokenConstant;
import com.dyna.domain.dto.LoginUser;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * 安全服务工具类
 *
 * copy from yudao-spring-boot-starter-security 的 SecurityFrameworkUtils 类
 *
 * @author 芋道源码
 */
@Slf4j
public class SecurityFrameworkUtils {

    private SecurityFrameworkUtils() {}

    /**
     * 从请求中，获得认证 Token
     *
     * @param exchange 请求
     * @return 认证 Token
     */
    public static String obtainAuthorization(ServerWebExchange exchange) {
        String authorization = exchange.getRequest().getHeaders().getFirst(TokenConstant.AUTHORIZATION);
        if (!StringUtils.hasText(authorization)) {
            return null;
        }
        int index = authorization.indexOf(TokenConstant.BEARER_SPACE);
        if (index == -1) { // 未找到
            return null;
        }
        return authorization.substring(index + 7).trim();
    }

    /**
     * 设置登录用户
     *
     * @param exchange 请求
     * @param user 用户
     */
    public static void setLoginUser(ServerWebExchange exchange, LoginUser user) {
//        exchange.getAttributes().put(TokenConstant.LOGIN_USER_HEADER, user);
    }

    /**
     * 移除请求头的用户
     *
     * @param exchange 请求
     * @return 请求
     */
    public static ServerWebExchange removeLoginUser(ServerWebExchange exchange) {
        // 如果不包含，直接返回
        if (!exchange.getRequest().getHeaders().containsKey(TokenConstant.LOGIN_USER_HEADER)) {
            return exchange;
        }
        // 如果包含，则移除。参考 RemoveRequestHeaderGatewayFilterFactory 实现
        ServerHttpRequest request = exchange.getRequest().mutate()
                .headers(httpHeaders -> httpHeaders.remove(TokenConstant.LOGIN_USER_HEADER)).build();
        return exchange.mutate().request(request).build();
    }

    /**
     * 将 user 并设置到 login-user 的请求头，使用 json 存储值
     * HTTP Header编码限制：HTTP请求头默认使用ISO-8859-1编码，不支持中文字符
     * 编码不一致：存储时使用UTF-8编码，但HTTP Header传输时被转换为ISO-8859-1
     * 浏览器/服务器处理：在传输过程中字符集转换不当
     * @param builder 请求
     * @param user 用户
     */
    @SneakyThrows
    public static void setLoginUserHeader(ServerHttpRequest.Builder builder, LoginUser user) {
        try {
            // 存储到Header时进行Base64编码
            String userInfoJson = JSON.toJSONString(user);
            String encodedUserInfo = Base64.getEncoder().encodeToString(userInfoJson.getBytes(StandardCharsets.UTF_8));
            builder.header(TokenConstant.LOGIN_USER_HEADER, encodedUserInfo);
        } catch (Exception ex) {
            log.error("[setLoginUserHeader][序列化 user({}) 发生异常]", user, ex);
            throw ex;
        }
    }

}
